昨天講了方法,今天講結果。
18 張統整卡,逐項查完之後:8 處錯誤。
但這篇真正想講的不是那個數字。是錯誤的分佈——它們不是隨機落下來的。
關於編號: 以下所有 PR 編號與卡片名稱都經過代換。但「這個編號存不存在」「哪一個在前哪一個在後」「主旨符不符合」全部與實際情況一致——會影響推論的部分,我一個都沒有動。
關於執行: 昨天講過,實際去搜尋、grep、比對日期的是 AI,我下指令。判準、範圍與最後的判定是我的。每一項都是二元結果、都附查詢證據、都可以被重跑——這是我敢把執行交出去的理由,也是它跟「讓 AI 自己寫 AC 自己測」的差別。
組織管理卡上有兩處寫著:
❌ 仍是問題(根因已明,待實作)……尚未看到對應的 PR / merge 紀錄
查下去的結果是:兩項都已經修好並合併了:
這一處為什麼最嚴重?不是因為它錯得最離譜,而是因為:
它在時間上是不可能的。
那兩個 PR 的合併日期,早於這張卡片最後更新的日期。也就是說,在那份統整被寫下來的時候,「已經修好了」這件事早就存在於資料裡了。
它不是「還沒更新到最新狀態」——它是看著已經存在的資料,寫出了相反的結論。
而這種錯的下游成本很具體:有人會照著這張卡去修一個已經修好的東西、或是重新開一張卡追一個已經結案的問題。它製造的不是困惑,是工。
| 卡片 | 卡片上的宣稱 | 實際 |
|---|---|---|
| 行銷來源卡 | PR #1305 修了分頁的歸屬邏輯 | 該 repo 沒有 #1305;同卡提到的另一個編號存在,而且確實涵蓋了這件事 |
| 技術屬性卡 | PR #2016 把某欄位併進列資料 | 該 repo 沒有 #2016 |
| 頂部導覽卡 | PR #1211、#1254 修了組織切換跳回 | 沒有 #1211;#1254 存在,而且確實涵蓋了該修復 |
這一類是最容易查的——輸入編號、按 Enter,存在或不存在,五秒鐘。
但它也是最容易騙過人的。
因為一個 PR 編號長什麼樣子?四位數字。沒有校驗碼、沒有格式特徵、沒有任何東西能讓你一眼看出 #1305 是假的而 #1312 是真的。
它們長得一模一樣。
而且注意那兩張卡的模式:假編號旁邊,就坐著一個真編號。 #1211 是假的,#1254 是真的,寫在同一行。
這就是 Day 1 那段假規則的結構——錯的東西被對的東西夾著,而你會用對的那個去替整行背書。
技術屬性卡說:
#2108 把 carrier 相關欄位併進了列表的資料結構
#2108 確實存在。但它做的是另一件事——伺服器端分組的欄位解析。
真正把那個欄位暴露到列表資料裡的,是 #2002。
我特別把這一處單獨列出來,因為它跟前兩類性質不一樣。
前兩類你去查一下就破功了:狀態誤判,比對日期就知道;假編號,按 Enter 就知道。
但這一處,如果只查「#2108 存不存在」——它會通過。
編號是真的、格式是對的、PR 也真的跟這張卡的主題沾得上邊。要抓到它,查核得多做一步:點進去,讀它到底做了什麼。
而那一步是我在指令裡自己加上去的,不是方法本身要求的。如果我當時沒有多寫那一句,這一處就會活下來。
而它正好是明天那篇的預告。
這一類最輕,但很有代表性。
檢視設定卡寫著「共有九個分頁」——然後在同一張卡上,自己列出了 10 條路由。程式碼裡也確實是 10 個。
它列對了清單,卻數錯了自己列的東西。
帳號狀態卡提到一個前端訊號叫 unreadableAccountId。這個名字在程式碼裡不存在。實際的實作用的是另外兩個變數名。
有意思的是:那張卡對「行為」的描述完全正確。 它知道那個機制在做什麼、什麼時候會觸發、影響到哪裡——只有名字是編的。
它理解了那件事,然後幫它取了一個聽起來很合理的名字。
如果這篇只寫到這裡,它會變成一篇「AI 不可靠」的文章。而那是錯的。
同一批卡片裡,資安相關的宣稱,全部正確。
其中最關鍵的一條是:某個服務的主要路由群組完全沒有身分驗證,任何人都可以直接讀到資料。這是一個真實存在、而且當時還沒修的授權缺口。
查證結果:屬實。
而更讓我意外的是下一層:卡片還寫了為什麼不馬上修。理由是另一個系統呼叫它的時候,根本沒有帶憑證的能力;如果現在強制加上驗證,正式環境會全面失效。
那個說法也被逐項查過——也屬實。 那個客戶端程式收了金鑰參數,但從頭到尾沒有使用它;所有呼叫端傳進去的都是空字串。
那不是一句「看起來很合理」的話。那是一個需要跨兩個系統、讀進去看實作細節才能得到的判斷,而且它是對的。
同一批驗證裡:10 個 PR、3 個前端 PR、5 個 commit hash——全部存在,主旨與日期都吻合。 另外 13 張卡,所有可驗證的宣稱都與程式碼一致。
把對的跟錯的擺在一起看,分界線其實很清楚:
| 結果 | |
|---|---|
| 有程式碼可以直接讀的 | 準確 |
| 需要跨系統推論的 | 開始猜 |
資安那批為什麼全對?因為答案就寫在檔案裡。打開路由設定、打開那個客戶端的實作,看一眼就能斷定——它不需要推論,它只需要讀。
PR 編號為什麼會錯?因為那需要跨出手上這份資料:你得去另一個系統查一個號碼、確認它的主旨、比對時間軸。而在做統整的當下,那個資訊不在它手上。
於是它做了一件很人性的事:填一個最合理的。
我覺得這是整個驗證裡最重要的發現,而且它是好消息:
它不是隨機出錯的。它的錯誤有結構。
隨機的錯只能靠運氣抓;有結構的錯可以預測,而可以預測的東西可以設計防線。
後來整個知識庫的架構,基本上就是從這張表長出來的:把需要推論的事情移到建置期去做,因為只有那裡驗證得了。
會。而且是兩種完全不同的懷疑。
這些票卡是層層疊疊、反反覆覆地被修改過的。同一個地方,三個月內可能被動過四次,每一次都留下一段敘述。
而更關鍵的是:開票的人不是我。
我不是那張卡的作者。我不確定當初預期它要長成什麼樣子,我只有事後看到的那些字。
所以我怕的是兩件事:
昨天我說過,判斷哪一本書才是「現在」,除了出版日期以外,唯一的途徑是我的腦袋。
今天要補一句更誠實的:
而我對那個索引本身,也沒有信心。
這個直接一點——我怕他騙我。
我知道這個說法不精確。它不會「騙」,它沒有動機、沒有意圖,它只是在資訊不足的時候產生了一個最合理的東西。
但對我來說,那個區別沒有意義:
「它不是故意的」和「它給了我一個錯的東西」,我承受的後果一模一樣。
昨天講的那 8 處錯,沒有一處是惡意的。而那份文件差點就被拿去給新人用了。
如果我不能相信自己的記憶,也不能相信它的判斷,那我還剩下什麼?
剩下證據。
那個編號存不存在,不取決於我記得什麼,也不取決於它說什麼——去儲存庫裡看一眼就知道。那個符號在不在程式碼裡,grep 的結果是零或不是零。
這就是為什麼昨天那張「判準必須二元」的表,對我來說不是形式主義。它是我在兩個都不可靠的證人之間,唯一的立足點:
當兩個證人都不可靠的時候,你需要的不是找一個更可靠的證人,是找物證。
(而這句話再往前推一步,就會推翻我整個作法。那是 Day 11。)
最後講一件事,它是明天那篇的入口。
這 8 處錯誤有一個共同點:它們全部都被我抓到了。
聽起來像廢話,但它其實是一個很強的性質——它們是可被查證的錯。去查一下就破功:編號不存在、日期對不上、數字兜不攏。
真正讓我後來睡不好的,是另一類錯:
那一類,你去查證的時候,每一項都會通過。
因為它的每一個零件都是真的。
明天那篇是這整個系列裡我最想寫的一篇。